package utils;

import android.util.Log;

public class ResolveDataUtil {
	private final int PROTOCOL_FF = (int) 0x01;
	public int PC_PROTOCOL = PROTOCOL_FF;// PC通讯协议
	public int nRecvProtType = 1;
	private Boolean isFFturntoData = false;
	private int g_nCountDataFF = 0;
	private byte byteVerifyFF = 0;
	private long nLastTime = 0;
	private final int nFrameTimeOut = 500;
	private int g_nLenDataFF = 0;
	public byte[] g_bytesRecv = new byte[512];

	public byte[] getG_bytesRecv() {
		return g_bytesRecv;
	}

	public void setG_bytesRecv(byte[] g_bytesRecv) {
		this.g_bytesRecv = g_bytesRecv;
	}

	public byte[] g_bytesRecv2 = new byte[512];

	public byte[] getG_bytesRecv2() {
		return g_bytesRecv2;
	}

	public void setG_bytesRecv2(byte[] g_bytesRecv2) {
		this.g_bytesRecv2 = g_bytesRecv2;
	}

	public int g_nCmd = 0;
	public int g_nCmd2 = 0;
	private int g_nLenFrameFF = 0;
	private int g_nStep55AA = 0;
	private int g_nStep55AA2 = 0;
	public int g_nLenFrame55AA = 0;
	public int g_nLenFrame55AA2 = 0;
	private int g_nLenData = 0;
	private int g_nLenData2 = 0;
	private int g_nPointData = 0;
	private int g_nPointData2 = 0;
	private final int STEP_55 = 0;
	private final int STEP_552 = 0;
	private final int STEP_AA = 1;
	private final int STEP_AA2 = 1;
	private final int STEP_CTRL = 2;
	private final int STEP_CTRL2 = 2;
	private final int STEP_LEN_1 = 3;
	private final int STEP_LEN_2 = 4;
	private final int STEP_LEN_1_1 = 3;
	private final int STEP_LEN_2_2 = 4;
	private final int STEP_CMD = 5;
	private final int STEP_CMD2 = 5;
	private final int STEP_DATA = 6;
	private final int STEP_DATA2 = 6;
	private final int STEP_VERIFY = 7;
	private final int STEP_VERIFY2 = 7;
	private final int STEP_END = 8;
	private final int STEP_END2 = 8;
	public static ResolveDataUtil util = null;
	private final int HAND_LOADLIST = (int) 0xD0; // 下载激活清单
	private final int HAND_READLIST = (int) 0xD2; // 读取激活清单
	private final int HAND_NUM_LIST = (int) 0xD1; // 读出激活清单总数
	private final int HAND_DEL_LIST = (int) 0xD3; // 删除
	private final int HAND_READ_LOG = (int) 0xD6; // 读取日志
	private final int HAND_NUM_LOG = (int) 0xD5; // 读取日志总数
	private final int HAND_DEL_LOG = (int) 0xD4; // 清除日志
	private final int HAND_SET_SYSTIME = (int) 0xDA;// 设置手持机时间
	public final int PROTOCOL_55AA = (int) 0x0;
	public int MODULAR_PROTOCOL = PROTOCOL_55AA;// 模块通讯协议
	public int m_nCDRsCtrl = 0x80;// 表示串口帧序号
	private boolean isSetProtocol = false;
	private boolean isDelHandSetLog = false;
	public int nChannel = 0;// 1表示PC，0表示模块

	// public byte[] ProtocolChange(byte[] bytesData, int nOffset, int nLen,
	// int nType) {
	// if (nType == 0) {// FF转55AA
	// return ProtocolOrganize55AA(bytesData, nOffset, nLen);
	// } else {// 55AA转FF
	// return ProtocolOrganizeFF(bytesData, nOffset, nLen);
	// }
	// }

	/**
	 * 数据协议解析
	 *
	 * @param data
	 * @param nLen
	 * @return
	 */
	public int AnalyData(byte[] data, int nLen) {
		int nRet = 0;
		nRecvProtType = PC_PROTOCOL;// 接收数据时按什么协议就发送什么协议

		nRet = Analy55AA(data, nLen);
		return nRet;
	}

	public int AnalyData2(byte[] data, int nLen) {
		int nRet = 0;
		nRet = Analy55AA2(data, nLen);
		return nRet;
	}

	int zonglen = 0;
	int zonglen2 = 0;
	int zonglens = 0;
	int zonglens2 = 0;

	public int getZonglens2() {
		return zonglens2;
	}

	public void setZonglens2(int zonglens2) {
		this.zonglens2 = zonglens2;
	}

	public int getZonglen2() {
		return zonglen2;
	}

	public void setZonglen2(int zonglen2) {
		this.zonglen2 = zonglen2;
	}

	public void IniAnaly55AA()
	{
		g_nStep55AA = STEP_55;
	}
	/**解析55AA协议数据,0表示数据有效,1表示数据未接收完,2表示校验出错,其他表示异常
	 * @param data
	 * @return
	 */
	public int Analy55AA2(byte[] data,int nLen)
	{
		zonglen += nLen;
		int nLenFrame= nLen;
		Log.e("7777", "xx"+nLenFrame);
		for(int i=0;i<nLenFrame;i++)
		{
			switch(g_nStep55AA)
			{
				case STEP_55://55
					if( (int)(data[i]&0xFF) == 0x55 )
					{
						g_nStep55AA = STEP_AA;
						g_nLenFrame55AA = 0;
						g_nPointData = 0;
						g_nLenData = 0;
						g_bytesRecv[g_nLenFrame55AA++] = data[i];
					}
					break;
				case STEP_AA:
					if( (int)(data[i]&0xFF) == 0xAA )
					{
						g_nStep55AA = STEP_CTRL;
						g_bytesRecv[g_nLenFrame55AA++] = data[i];
					}
					else
						g_nStep55AA = STEP_END;
					break;
				case STEP_CTRL:
					g_nStep55AA = STEP_LEN_1;
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					break;
				case STEP_LEN_1:
					if( (int)(data[i]&0xFF) == 0x00 )
					{
						g_nStep55AA = STEP_LEN_2;
						g_bytesRecv[g_nLenFrame55AA++] = data[i];
					}
					else
						g_nStep55AA = STEP_END;
					break;
				case STEP_LEN_2:
					g_nLenData = (int)(data[i]&0xFF);
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					g_nStep55AA = STEP_CMD;
					break;
				case STEP_CMD:
					g_nCmd = (int)(data[i]&0xFF);
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					g_nStep55AA = STEP_DATA;
					break;
				case STEP_DATA:
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					g_nPointData++;
					if( g_nPointData >= g_nLenData )
						g_nStep55AA = STEP_VERIFY;
					break;
				case STEP_VERIFY:
					byte byteVerify = 0;
					for( int k = 2; k < g_nLenFrame55AA; k++ )
					{
						byteVerify ^= g_bytesRecv[k];
					}
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					if(	byteVerify == data[i] )
					{
						g_nStep55AA = STEP_55;
						zonglen2 = zonglen;
						zonglen = 0;
						return 0;
					}else
					{
						g_nStep55AA = STEP_55;
						Log.e("test","计算校验"+HexUtil.BytesToString(g_bytesRecv,0,g_nLenFrame55AA));
						return 2;//校验出错
					}
					//break;
				default:
					g_nStep55AA = STEP_55;
					return 3;
			}
		}
		return 1;
	}


	public static ResolveDataUtil getResolveDataUtil() {
		if (util == null) {
			try {
				util = new ResolveDataUtil();
			} catch (SecurityException e) {
				e.printStackTrace();
			}
		}
		return util;
	}

	/**
	 * 解析55AA协议数据,0表示数据有效,1表示数据未接收完,2表示校验出错,其他表示异常
	 *
	 * @param data
	 * @return
	 */
	public int Analy55AA(byte[] data, int nLen) {
		zonglens += nLen;
		int nLenFrame = nLen;

		for (int i = 0; i < nLenFrame; i++) {
			switch (g_nStep55AA) {
				case STEP_55:// 55
					if ((int) (data[i] & 0xFF) == 0x55) {
						g_nStep55AA = STEP_AA;
						g_nLenFrame55AA = 0;
						g_nPointData = 0;
						g_nLenData = 0;
						g_bytesRecv[g_nLenFrame55AA++] = data[i];
					}
					break;
				case STEP_AA:
					if ((int) (data[i] & 0xFF) == 0xAA) {
						g_nStep55AA = STEP_CTRL;
						g_bytesRecv[g_nLenFrame55AA++] = data[i];
					} else
						g_nStep55AA = STEP_END;
					break;
				case STEP_CTRL:
					g_nStep55AA = STEP_LEN_1;
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					break;
				case STEP_LEN_1:
					if ((int) (data[i] & 0xFF) == 0x00) {
						g_nStep55AA = STEP_LEN_2;
						g_bytesRecv[g_nLenFrame55AA++] = data[i];
					} else
						g_nStep55AA = STEP_END;
					break;
				case STEP_LEN_2:
					g_nLenData = (int) (data[i] & 0xFF);
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					g_nStep55AA = STEP_CMD;
					break;
				case STEP_CMD:
					g_nCmd = (int) (data[i] & 0xFF);
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					g_nStep55AA = STEP_DATA;
					break;
				case STEP_DATA:
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					g_nPointData++;
					if (g_nPointData >= g_nLenData)
						g_nStep55AA = STEP_VERIFY;
					break;
				case STEP_VERIFY:
					byte byteVerify = 0;
					for (int k = 2; k < g_nLenFrame55AA; k++) {
						byteVerify ^= g_bytesRecv[k];
					}
					g_bytesRecv[g_nLenFrame55AA++] = data[i];
					if (byteVerify == data[i]) {
						g_nStep55AA = STEP_55;
						zonglens2 = zonglens;
						zonglens = 0;
						return 0;
					} else {
						g_nStep55AA = STEP_55;
						Log.e("test",
								"计算校验"
										+ HexUtil.BytesToString(g_bytesRecv, 0,
										g_nLenFrame55AA));
						return 2;// 校验出错
					}
					// break;
				default:
					g_nStep55AA = STEP_55;
					return 3;
			}
		}
		return 1;
	}

	public byte[] GetFrameData() {
		if (nChannel == 1)// PC通讯
		{
			if (PC_PROTOCOL == PROTOCOL_FF) {
				byte[] bytesTmp = new byte[g_nLenDataFF - 2];
				System.arraycopy(g_bytesRecv, 1, bytesTmp, 0, g_nLenDataFF - 2);
				return ProtocolOrganize55AA(bytesTmp);
			} else {
				byte[] bytesTmp = new byte[g_nLenFrame55AA];
				System.arraycopy(g_bytesRecv, 0, bytesTmp, 0, g_nLenFrame55AA);
				return bytesTmp;
			}
		} else// 模块通讯
		{
			// if( MODULAR_PROTOCOL == PROTOCOL_FF)
			// {
			// byte[] bytesTmp = new byte[g_nLenDataFF-2];
			// System.arraycopy(g_bytesRecv, 1, bytesTmp, 0,g_nLenFrameFF-2);
			// return ProtocolOrganize55AA(bytesTmp);
			// }
			// else
			{
				byte[] bytesTmp = new byte[g_nLenFrame55AA];
				System.arraycopy(g_bytesRecv, 0, bytesTmp, 0, g_nLenFrame55AA);
				return bytesTmp;
			}
		}

	}

	// /**
	// * 按55AA协议组织发送的报文
	// * @param nCmd
	// * @param bytesValue
	// * @return
	// */
	// public byte[] ProtocolOrganize55AA(byte[] bytesValue,int nOffset,int
	// nLenData)
	// {
	// byte Verify=0;
	// int nCtrl = 0;
	// int nLen = 3+2+nLenData+1;
	// int i=0;
	// byte[] bytesSend = new byte[nLen];
	//
	// if((m_nCDRsCtrl&0x0F) > 0x07) m_nCDRsCtrl = 0x80;
	// else m_nCDRsCtrl += 1;
	//
	// nCtrl = m_nCDRsCtrl;
	//
	// bytesSend[0] = (byte)0x55;
	// bytesSend[1] = (byte)0xAA;
	// bytesSend[2] = (byte)nCtrl;
	// bytesSend[3] = (byte)0x00;
	// bytesSend[4] = (byte)(nLenData-1);
	// System.arraycopy( bytesValue, nOffset, bytesSend, 5, nLenData );
	// for(i=0;i<(nLenData+3) ;i++)
	// Verify ^= bytesSend[2+i];
	// bytesSend[bytesSend.length-1] = Verify;
	// return bytesSend;
	// }
	//

	/**
	 * 按55AA协议组织发送的报文
	 *
	 * @param nCmd
	 * @param bytesValue
	 * @return
	 */
	public byte[] ProtocolOrganize55AA(byte[] bytesValue) {
		byte Verify = 0;
		int nCtrl = 0;
		int nLen = 3 + 2 + bytesValue.length + 1;
		int i = 0;
		byte[] bytesSend = new byte[nLen];

		if ((m_nCDRsCtrl & 0x0F) > 0x07)
			m_nCDRsCtrl = 0x80;
		else
			m_nCDRsCtrl += 1;

		nCtrl = 0x80;

		bytesSend[0] = (byte) 0x55;
		bytesSend[1] = (byte) 0xAA;
		bytesSend[2] = (byte) nCtrl;
		bytesSend[3] = (byte) 0x00;
		bytesSend[4] = (byte) (bytesValue.length - 1);
		System.arraycopy(bytesValue, 0, bytesSend, 5, bytesValue.length);
		for (i = 0; i < (bytesValue.length + 3); i++)
			Verify ^= bytesSend[2 + i];
		bytesSend[bytesSend.length - 1] = Verify;
		return bytesSend;
	}

	public static Boolean boolRecv = true;// 发送后不接收

	/**
	 * 解析PC端数据，分类返回值 非0表示发送给底层,0表示android处理，
	 *
	 * @param nCmd
	 * @return
	 */
	public int CmdAnaly(byte[] bytesValues, int nOffset, int nLenValue) {
		int nRet = 1;
		int nCmd = g_nCmd;
		boolRecv = true;
		switch (nCmd) {
			case HAND_SET_SYSTIME:
				nRet = 0;
				break;
			case HAND_READ_LOG:// D6协议设置冲突
				if (nLenValue != 5) {
					isSetProtocol = true;
				}
				nRet = 0;
				break;
			case HAND_DEL_LOG:// 读参数冲突
				if (nLenValue == 2 && bytesValues[nOffset + 1] == 1) {
					isDelHandSetLog = true;
				}
				nRet = 0;
				break;
			case 0xF2:
				if (bytesValues[nOffset + 1] == 0x00)
					boolRecv = false;
				nRet = 2;
				break;
			case 0xF0:
				nRet = 0;
				break;
			case 0xC0:
				nRet = 0;
				break;
			case 0xA5:
				if (bytesValues[nOffset + 1] == 0x00)// 重发次数
					boolRecv = false;
				nRet = 2;
				break;
			case 0xA9:
				nRet = 0;
				break;
			default:
				nRet = 2;
				break;
		}
		return nRet;
	}

	public byte[] ProtocolOrganize(byte[] bytesValue) {
		return ProtocolOrganize(bytesValue, 0, bytesValue.length);
	}

	public byte[] ProtocolOrganize(byte[] bytesValue, int nOffset, int nLenData) {
		if (nRecvProtType == PROTOCOL_FF)
			return ProtocolOrganizeFF(bytesValue, nOffset, nLenData);
		else
			return ProtocolOrganize55AA(bytesValue, nOffset, nLenData);
	}

	/**
	 * 按55AA协议组织发送的报文
	 *
	 * @param nCmd
	 * @param bytesValue
	 * @return
	 */
	public byte[] ProtocolOrganize55AA(byte[] bytesValue, int nOffset,
									   int nLenData) {
		byte Verify = 0;
		int nCtrl = 0;
		int nLen = 3 + 2 + nLenData + 1;
		int i = 0;
		byte[] bytesSend = new byte[nLen];

		if ((m_nCDRsCtrl & 0x0F) > 0x07)
			m_nCDRsCtrl = 0x80;
		else
			m_nCDRsCtrl += 1;

		nCtrl = m_nCDRsCtrl;

		bytesSend[0] = (byte) 0x55;
		bytesSend[1] = (byte) 0xAA;
		bytesSend[2] = (byte) nCtrl;
		bytesSend[3] = (byte) 0x00;
		bytesSend[4] = (byte) (nLenData - 1);
		System.arraycopy(bytesValue, nOffset, bytesSend, 5, nLenData);
		for (i = 0; i < (nLenData + 3); i++)
			Verify ^= bytesSend[2 + i];
		bytesSend[bytesSend.length - 1] = Verify;
		return bytesSend;
	}

	public byte[] ProtocolOrganizeFF(byte[] bytesValue, int nOffset,
									 int nLenData) {
		byte Verify = 0;
		int nCtrl = 0;
		int nLen = nLenData;
		int i = 0;
		int nCount = 0;
		byte[] bytesSend = new byte[256];

		if ((m_nCDRsCtrl & 0x0F) > 0x07)
			m_nCDRsCtrl = 0x80;
		else
			m_nCDRsCtrl += 1;

		nCtrl = m_nCDRsCtrl;
		nCount = 0;
		bytesSend[nCount++] = (byte) 0xFF;
		bytesSend[nCount++] = (byte) 0xFF;
		bytesSend[nCount++] = (byte) nCtrl;
		Verify = 0;
		Verify ^= bytesSend[nCount - 1];
		for (i = 0; i < nLen; i++) {
			Verify ^= bytesValue[nOffset + i];
			if (bytesValue[nOffset + i] == (byte) 0xFF) {
				bytesSend[nCount++] = (byte) 0xFE;
				bytesSend[nCount++] = 0x01;
			} else if (bytesValue[nOffset + i] == (byte) 0xFE) {
				bytesSend[nCount++] = (byte) 0xFE;
				bytesSend[nCount++] = 0x00;
			} else {
				bytesSend[nCount++] = bytesValue[nOffset + i];
			}
		}
		if (Verify == (byte) 0xFF) {
			bytesSend[nCount++] = (byte) 0xFE;
			bytesSend[nCount++] = 0x01;
		} else if (Verify == (byte) 0xFE) {
			bytesSend[nCount++] = (byte) 0xFE;
			bytesSend[nCount++] = 0x00;
		} else {
			bytesSend[nCount++] = Verify;
		}
		bytesSend[nCount++] = (byte) 0xFF;// 结尾
		byte[] bytesSend2 = new byte[nCount];
		System.arraycopy(bytesSend, 0, bytesSend2, 0, nCount);
		return bytesSend2;
	}

	public int AnalyFF(byte[] data, int nLen) {
		// if((System.currentTimeMillis()-nLastTime) > nFrameTimeOut)
		// {//帧超时
		// //nFrameTimeOut
		// }

		int nLenFrame = nLen;

		for (int i = 0; i < nLenFrame; i++) {
			if ((int) (data[i] & 0xFF) == 0xFF) {
				isFFturntoData = false;
				if (g_nCountDataFF > 3) {
					// byte byteVerify = 0;
					// for( int k = 0; k < g_nCountDataFF; k++ )
					// {
					// byteVerify ^= g_bytesRecv[k];
					// }
					if (byteVerifyFF == 0) {// 校验通过
						// 转义
						g_nLenDataFF = ChangeDataToFF(g_bytesRecv,
								g_nCountDataFF);
						// listData.add(HexUtil.BytesToString(g_bytesRecv, 2,
						// g_nLenDataFF-3));//扣款头一字帧序号，命令字，尾一字节校验
						g_nCmd = (int) (g_bytesRecv[1] & 0xFF);
						g_nLenFrameFF = g_nLenDataFF + 2;// 头和尾各一个FF
						g_nCountDataFF = 0;
						return 0;
					} else {
						g_nCountDataFF = 0;
						return 2;// 校验出错
					}

				}
				g_nCountDataFF = 0;
			} else {
				if (isFFturntoData == false) {
					isFFturntoData = true;
					// 上次接收数据时间
					nLastTime = System.currentTimeMillis();
					g_nLenDataFF = 0;
					byteVerifyFF = 0;
					g_nCountDataFF = 0;
				}
				g_bytesRecv[g_nCountDataFF++] = data[i];
				byteVerifyFF ^= data[i];
			}
		}
		return 1;
	}

	/**
	 * 将数据中FE转义
	 *
	 * @param bytesData
	 * @param nLen转义前数据长度
	 * @return转义后数据长度
	 */
	private int ChangeDataToFF(byte[] bytesData, int nLen) {
		int nByte;
		int nLenCount = 0;
		for (int i = 0; i < nLen; i++) {
			nByte = (int) (bytesData[i] & 0xFF);
			if (nByte == 0xFE) {
				if (bytesData[i + 1] == 0x00)// FE
				{
					bytesData[nLenCount++] = bytesData[i];
					i++;

				} else if (bytesData[i + 1] == 0x01)// FF
				{
					bytesData[nLenCount++] = (byte) 0xFF;
					i++;
				} else
					bytesData[nLenCount++] = bytesData[i];
			} else {
				bytesData[nLenCount++] = bytesData[i];
			}
		}
		return nLenCount;
	}

	public byte[] GetFrameData55AA() {
		byte[] bytesTmp = new byte[g_nLenFrame55AA];
		System.arraycopy(g_bytesRecv, 0, bytesTmp, 0, g_nLenFrame55AA);
		return bytesTmp;
	}
}
